package com.csw.android.androidtest.net.socket.base;

import com.csw.android.dev_utils.handler.ThreadWithHandler;

public abstract class BaseSocket {
    protected SocketListener socketListener;
    protected String ip;
    protected int port;
    protected String destIP;
    protected int destPort;
    //socket状态，0初始化，1等待连接，2读取中，3正常关闭，-1异常关闭。
    private int state = 0;
    private final ThreadWithHandler readThread = new ThreadWithHandler("readThread", Thread.NORM_PRIORITY, null);
    private final ThreadWithHandler writeThread = new ThreadWithHandler("writeThread", Thread.NORM_PRIORITY, null);

    public BaseSocket(SocketListener socketListener) {
        this.socketListener = socketListener;
    }

    //----------------------------------------------------------------------------------------------

    /**
     * 进入准备状态，服务端等待客户端连接，客户端连接服务端，此方法仅允许调用一次
     */
    public void prepare() {
        if (state != 0) {
            return;
        }
        state = 1;
        readThread.start();
        readThread.getHandlerProxy().post(new Runnable() {
            @Override
            public void run() {
                try {
                    //连接
                    execConnect();
                    //连接成功启动写入线程
                    writeThread.start();
                } catch (Exception e) {
                    onError(e);
                }
            }
        });
    }

    /**
     * 设置通讯目标信息
     * @param ip  IP地址
     * @param port 端口
     */
    public void setDestInfo(String ip, int port) {
        destIP = ip;
        destPort = port;
    }

    public void startRead(){
        readThread.getHandlerProxy().post(new Runnable() {
            @Override
            public void run() {
                try {
                    state = 2;
                    //开始循环读取数据
                    execRead();
                } catch (Exception e) {
                    onError(e);
                }
            }
        });
    }

    private void onError(Exception e) {
        state = -1;
        closeResource();
        socketListener.onError(e);
    }

    /**
     * 写入数据
     *
     * @param data 字节数组
     */
    public void write(byte[] data) {
        writeThread.getHandlerProxy().post(new Runnable() {
            @Override
            public void run() {
                try {
                    execWrite(data);
                } catch (Exception e) {
                    onError(e);
                }
            }
        });
    }

    /**
     * 关闭socket,读取线程强行关闭，写入线程等待之前提交的所有任务执行完毕再关闭
     */
    public void close() {
        state = 3;
        closeResource();
        socketListener.onClose();
    }

    public int getState() {
        return state;
    }

    /**
     * 关闭资源
     */
    protected void closeResource() {
        readThread.quit();
        writeThread.quitSafely();
    }

    public String getIp() {
        return ip;
    }

    public int getPort() {
        return port;
    }

    //----------------------------------------------------------------------------------------------

    /**
     * 读取线程执行连接
     */
    protected abstract void execConnect() throws Exception;

    /**
     * 读取线程读数据，读取到的数据通过socketListener返回
     */
    protected abstract void execRead() throws Exception;

    /**
     * 写线程输出数据
     *
     * @param data 要输出的字节数组
     */
    protected abstract void execWrite(byte[] data) throws Exception;

}
